package edu.cs.usask.ca.silver.businesslogic.commands.generic;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.UUID;

import edu.cs.usask.ca.silver.api.businesslogic.GroupI;
import edu.cs.usask.ca.silver.api.persistence.StorageI;
import edu.cs.usask.ca.silver.businesslogic.ids.GroupID;
import edu.cs.usask.ca.silver.businesslogic.ids.ModelProjectID;
import edu.cs.usask.ca.silver.businesslogic.ids.UserID;
import edu.cs.usask.ca.silver.businesslogic.util.SilverAutoManagedObjectFactory;
import edu.cs.usask.ca.silver.businesslogic.util.SilverBLTransactionManager;
import edu.cs.usask.ca.silver.definitions.Exposure;

/**
 * Implementation of the Group interface.
 * 
 * @author Yudi Xue
 * 
 */
public class Group implements GroupI {

	private static final SilverAutoManagedObjectFactory groupFactory = new SilverAutoManagedObjectFactory(
			"edu.cs.usask.ca.silver.businesslogic.commands.generic.Group");

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#createGroup(java.lang
	 * .String, edu.cs.usask.ca.silver.businesslogic.ids.UserID,
	 * java.lang.String, java.lang.String)
	 */

	public GroupID createGroup(String gName, UserID gOwnerId,
			Exposure gPrivacy, String gDescription, StorageI storage) throws Exception {
		GroupID result;
		boolean error = false;

		try {
			SilverBLTransactionManager.startTransaction();
			UUID groupId = storage.addGroup(gName,
					gOwnerId.getUUIdVal(), gPrivacy.name(), gDescription);
			storage.addUserToGroup(gOwnerId.getUUIdVal(),
					groupId);

			result = new GroupID(groupId);
		} catch (Exception e) {
			error = true;
			throw e;
		} finally {
			try {
				SilverBLTransactionManager.closeTransaction(error);
			} catch (Exception e) {
				throw e;
			}
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see edu.cs.usask.ca.silver.api.businesslogic.GroupI#getAllGroupIDs()
	 */
	public GroupID[] getAllGroupIDs(StorageI storage) throws Exception {
		ArrayList<UUID> result;

		result = storage.getAllGroupIDs();
		GroupID[] ids = new GroupID[result.size()];

		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			UUID temp = e.next();
			ids[i++] = new GroupID(temp);
		}

		return ids;
	}

	public String[] getAllGroupNames(StorageI storage) throws Exception {
		ArrayList<String> result;
		result = storage.getAllGroupNames();
		String[] names = new String[result.size()];

		int i = 0;
		Iterator<String> e = result.iterator();
		while (e.hasNext()) {
			String temp = e.next();
			names[i++] = temp;
		}

		return names;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getContainedModelProjectIDs
	 * (edu.cs.usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public ModelProjectID[] getContainedModelProjectIDs(GroupID groupId, StorageI storage)
			throws Exception {
		ArrayList<UUID> result;
		result = storage.getGroupContainingModelProjectIDs(
				groupId.getUUIdVal());
		ModelProjectID[] ids = new ModelProjectID[result.size()];
		int i = 0;
		Iterator<UUID> e = result.iterator();
		while (e.hasNext()) {
			UUID temp = e.next();
			ids[i++] = new ModelProjectID(temp);
		}
		return ids;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getName(edu.cs.usask.
	 * ca.silver.businesslogic.ids.GroupID)
	 */
	public String getName(GroupID groupId, StorageI storage) throws Exception {
		return storage.getGroupName(groupId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getPrivacy(edu.cs.usask
	 * .ca.silver.businesslogic.ids.GroupID)
	 */
	public String getPrivacy(GroupID groupId, StorageI storage) throws Exception {
		return storage.getGroupPrivacy(groupId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getOwnerUserID(edu.cs
	 * .usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public UserID getOwnerUserID(GroupID groupId, StorageI storage) throws Exception {
		UUID userIdVal = storage.getGroupOwnerID(
				groupId.getUUIdVal());
		return new UserID(userIdVal);
	}

	public String getOwnerUserName(GroupID groupId, StorageI storage) throws Exception {
		return storage.getGroupOwnerName(
				groupId.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getDescription(edu.cs
	 * .usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public String getDescription(GroupID groupID, StorageI storage) throws Exception {
		return storage.getGroupDescription(
				groupID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getCreationDate(edu.cs
	 * .usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public Date getCreationDate(GroupID groupID, StorageI storage) throws Exception {
		return storage.getGroupCreationDate(
				groupID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#getCreationTime(edu.cs
	 * .usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public Date getCreationTime(GroupID groupID, StorageI storage) throws Exception {
		return storage.getGroupCreationDate(
				groupID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#setName(edu.cs.usask.
	 * ca.silver.businesslogic.ids.GroupID, java.lang.String)
	 */
	public boolean setName(GroupID groupID, String newName, StorageI storage) throws Exception {
		return storage.setGroupName(groupID.getUUIdVal(),
				newName);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#setExposure(edu.cs.usask
	 * .ca.silver.businesslogic.ids.GroupID,
	 * edu.cs.usask.ca.silver.helper.Exposure)
	 */
	public boolean setExposure(GroupID groupID, Exposure newExposure, StorageI storage)
			throws Exception {
		return storage.setGroupPrivacy(groupID.getUUIdVal(),
				newExposure.name());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#setOwner(edu.cs.usask
	 * .ca.silver.businesslogic.ids.GroupID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.UserID)
	 */
	public boolean setOwner(GroupID groupID, UserID userID, StorageI storage) throws Exception {
		return storage.setGroupOwnerID(groupID.getUUIdVal(),
				userID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#setDescription(edu.cs
	 * .usask.ca.silver.businesslogic.ids.GroupID, java.lang.String)
	 */
	public boolean setDescription(GroupID groupID, String description, StorageI storage)
			throws Exception {
		return storage.setGroupDescription(
				groupID.getUUIdVal(), description);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#deleteGroup(edu.cs.usask
	 * .ca.silver.businesslogic.ids.GroupID)
	 */
	public boolean deleteGroup(GroupID groupID, StorageI storage) throws Exception {
		return storage.deleteGroup(groupID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#addUser(edu.cs.usask.
	 * ca.silver.businesslogic.ids.UserID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public boolean addUser(UserID userID, GroupID groupID, StorageI storage) throws Exception {
		return storage.addUserToGroup(userID.getUUIdVal(),
				groupID.getUUIdVal());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * edu.cs.usask.ca.silver.api.businesslogic.GroupI#removeUserFromGroup(edu
	 * .cs.usask.ca.silver.businesslogic.ids.UserID,
	 * edu.cs.usask.ca.silver.businesslogic.ids.GroupID)
	 */
	public boolean removeUserFromGroup(UserID userID, GroupID groupID, StorageI storage)
			throws Exception {
		return storage.removeUserFromGroup(
				userID.getUUIdVal(), groupID.getUUIdVal());
	}

	public static SilverAutoManagedObjectFactory getObjectPoolFactory() {
		return groupFactory;
	}

	public HashMap<UUID, String> getAllGroupIDsAndNames(StorageI storage) throws Exception {
		return storage.getAllGroupIDNameAsHashedMap();
	}

}
